﻿/*
-----------------------------------------------------------------------------
This source file is part of Cell Cloud.

Copyright (c) 2009-2012 Cell Cloud Team (cellcloudproject@gmail.com)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/

#include "CellStableHeaders.h"
#include "CellTalkServiceFlashAddon.h"
#include "CellBlockingAcceptor.h"
#include "CellNonblockingAcceptor.h"
#include "CellMessage.h"
#include "CellSession.h"
#include "CellLoggerManager.h"
#include "CellStringConverter.h"
#include "CellUtil.h"

namespace cell
{

#define NULL_CONNECTION_TIMEOUT 15000

//-----------------------------------------------------------------------
FlashAddon::FlashAddon(void)
	: mAcceptor(NULL)
	, mHandler(NULL)
	, mLatched(true)
{
}
//-----------------------------------------------------------------------
FlashAddon::~FlashAddon(void)
{
	shutdown();
}
//-----------------------------------------------------------------------
bool FlashAddon::startup(void)
{
	if (mHandler == NULL)
		mHandler = CELL_NEW FlashAddonAcceptorHandler();
	if (mAcceptor == NULL)
		mAcceptor = CELL_NEW BlockingAcceptor();

	mAcceptor->setMaxConnectNum(48);
	mAcceptor->setHandler(mHandler);

	bool ret = mAcceptor->bind(843);
	if (ret)
		mLatched = false;

	return ret;
}
//-----------------------------------------------------------------------
void FlashAddon::shutdown(void)
{
	mLatched = true;

	if (mAcceptor != NULL)
	{
		mAcceptor->unbind();
		CELL_DELETE mAcceptor;
		mAcceptor = NULL;
	}
	if (mHandler != NULL)
	{
		CELL_DELETE mHandler;
		mHandler = NULL;
	}
}
//-----------------------------------------------------------------------
void FlashAddon::tick(uint64 current)
{
	if (mLatched)
		return;

	SessionIdList sessionIds;
	mAcceptor->listSessionIds(sessionIds);
	if (sessionIds.empty())
		return;

	uint64 time = 0;
	SessionIdList::iterator iter, end = sessionIds.end();
	for (iter = sessionIds.begin(); iter != end; ++iter)
	{
		Session* session = mAcceptor->getSession((*iter));
		if (NULL == session)
			continue;

		{
			CELL_LOCK_MUTEX(mHandler->mMutex);

			if (session->getCustomData().length() == 0)
				continue;

			time = StringConverter::parseUnsignedInteger64(session->getCustomData());
		}

		if (time == 1)
		{
			mAcceptor->close(session);
		}
		else if (current - time >= NULL_CONNECTION_TIMEOUT)
		{
			mAcceptor->close(session);
		}
	}
}


//-----------------------------------------------------------------------
FlashAddonAcceptorHandler::FlashAddonAcceptorHandler(void)
{
}
//-----------------------------------------------------------------------
FlashAddonAcceptorHandler::~FlashAddonAcceptorHandler(void)
{
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::sessionCreated(Session* session)
{
	CELL_LOCK_MUTEX(mMutex);
	session->setCustomData(StringConverter::toString((uint64)2));
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::sessionDestroyed(Session* session)
{
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::sessionOpened(Session* session)
{
	CELL_LOCK_MUTEX(mMutex);
	session->setCustomData(StringConverter::toString((uint64)Util::currentTimeMillis()));
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::sessionClosed(Session* session)
{
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::messageReceived(Session* session, Message* message)
{
	if (message->length() > 255)
		return;

	char data[256] = {0x0};
	message->get(data);
	if (stricmp(data, "<policy-file-request/>") == 0)
	{
		char szPolicy[256] = {0x0};
		strcat(szPolicy, "<?xml version=\"1.0\"?>");
		strcat(szPolicy, "<cross-domain-policy>");
		strcat(szPolicy, "<site-control permitted-cross-domain-policies=\"all\"/>");
		strcat(szPolicy, "<allow-access-from domain=\"*\" to-ports=\"*\"/>");
		strcat(szPolicy, "</cross-domain-policy>\0");

		Message policy(szPolicy, strlen(szPolicy));
		session->write(&policy);

		/*
		char log[256] = {0x0};
		sprintf(log, "Flash addon service response policy file to %s:%d",
			session->getAddress().getHostAddress().c_str(),
			session->getAddress().getPort());
		LoggerManager::getSingleton().log(log);
		*/
	}
	else
	{
		char szPolicy[256] = {0x0};
		strcat(szPolicy, "<?xml version=\"1.0\"?>");
		strcat(szPolicy, "<cross-domain-policy>");
		strcat(szPolicy, "<site-control permitted-cross-domain-policies=\"all\"/>");
		strcat(szPolicy, "<allow-access-from domain=\"*\" to-ports=\"*\"/>");
		strcat(szPolicy, "</cross-domain-policy>\0");

		Message policy(szPolicy, strlen(szPolicy));
		session->write(&policy);

		/*
		char log[256] = {0x0};
		sprintf(log, "Flash addon service detects suspicious session %s:%d",
			session->getAddress().getHostAddress().c_str(),
			session->getAddress().getPort());
		LoggerManager::getSingleton().log(log);
		*/
	}
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::messageSent(Session* session, Message* message)
{
	// 修改标识
	CELL_LOCK_MUTEX(mMutex);
	session->setCustomData(StringConverter::toString((uint64)1));
}
//-----------------------------------------------------------------------
void FlashAddonAcceptorHandler::errorOccurred(uint16 errorCode, Session* session)
{
	/*
	char log[256] = {0x0};
	sprintf(log, "Flash addon service error %d at %s:%d",
		errorCode,
		session->getAddress().getHostAddress().c_str(),
		session->getAddress().getPort());
	LoggerManager::getSingleton().log(log);
	*/
}

} // end namespace cell
